using Microsoft.AspNetCore.SignalR;
using ProduceBasicData.Api.DTO;
using ProduceBasicData.Api.Hubs;
using ProduceBasicData.Domain.Entities;
using ProduceBasicData.ErrorCode;
using ProduceBasicData.Infrastructure.Interface;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.Extensions.Logging;

namespace ProduceBasicData.Api.Services
{
    /// <summary>
    /// 通知服务实现
    /// </summary>
    public class NotificationService : INotificationService
    {
        private readonly IHubContext<NotificationHub> _hubContext;
        private readonly IBaseRespository<NotificationModel> _notificationRepository;
        private readonly ILogger<NotificationService> _logger;

        public NotificationService(
            IHubContext<NotificationHub> hubContext,
            IBaseRespository<NotificationModel> notificationRepository,
            ILogger<NotificationService> logger)
        {
            _hubContext = hubContext;
            _notificationRepository = notificationRepository;
            _logger = logger;
        }

        /// <summary>
        /// 发送工单下发通知
        /// </summary>
        public async Task<ApiResult<bool>> SendWorkOrderIssueNotificationAsync(string workOrderCode, string message)
        {
            var result = new ApiResult<bool>();
            try
            {
                var notification = new RealtimeNotificationDto
                {
                    Title = "工单下发通知",
                    Content = message,
                    Type = 1,
                    WorkOrderCode = workOrderCode,
                    Priority = 2,
                    CreateTime = DateTime.Now
                };

                // 保存到数据库
                var notificationEntity = new NotificationModel
                {
                    Title = notification.Title,
                    Content = notification.Content,
                    Type = notification.Type,
                    WorkOrderCode = notification.WorkOrderCode,
                    Priority = notification.Priority,
                    CreateTime = DateTime.Now,
                    CreateName = "系统"
                };

                await _notificationRepository.AddAsync(notificationEntity);
                notification.Id = notificationEntity.Id; // 更新实时通知ID

                // 发送实时通知
                await _hubContext.Clients.All.SendAsync("ReceiveNotification", notification);

                result.Code = ApiEnum.Success;
                result.Msg = "工单下发通知发送成功";
                result.Data = true;

                _logger.LogInformation($"工单下发通知已发送: {workOrderCode}");
            }
            catch (Exception ex)
            {
                result.Code = ApiEnum.Failed;
                result.Msg = $"工单下发通知发送失败: {ex.Message}";
                result.Data = false;
                _logger.LogError(ex, "发送工单下发通知失败");
            }
            return result;
        }

        /// <summary>
        /// 发送报工单提交通知
        /// </summary>
        public async Task<ApiResult<bool>> SendProductionReportSubmitNotificationAsync(string productionReportCode, string message, int? userId = null, string? userName = null)
        {
            var result = new ApiResult<bool>();
            try
            {
                var notification = new RealtimeNotificationDto
                {
                    Title = "报工单提交通知",
                    Content = message,
                    Type = 2, // 报工单通知
                    TypeName = "报工单通知",
                    Tag = "报工", // 添加标签
                    ProductionReportCode = productionReportCode,
                    Priority = 2, // 中等优先级
                    PriorityColor = "#409EFF", // 蓝色
                    CreateTime = DateTime.Now,
                    ShowAsPopup = true,
                    PopupDuration = 3000
                };

                // 保存到数据库
                var notificationEntity = new NotificationModel
                {
                    Title = notification.Title,
                    Content = notification.Content,
                    Type = notification.Type,
                    Tag = "报工",
                    ProductionReportCode = notification.ProductionReportCode,
                    Priority = notification.Priority,
                    UserId = userId,
                    UserName = userName,
                    CreateTime = DateTime.Now,
                    CreateName = "系统"
                };

                await _notificationRepository.AddAsync(notificationEntity);
                notification.Id = notificationEntity.Id; // 更新实时通知ID

                // 发送实时通知
                await _hubContext.Clients.All.SendAsync("ReceiveNotification", notification);

                result.Code = ApiEnum.Success;
                result.Msg = "报工单提交通知发送成功";
                result.Data = true;

                _logger.LogInformation($"报工单提交通知已发送: {productionReportCode}");
            }
            catch (Exception ex)
            {
                result.Code = ApiEnum.Failed;
                result.Msg = $"报工单提交通知发送失败: {ex.Message}";
                result.Data = false;
                _logger.LogError(ex, "发送报工单提交通知失败");
            }
            return result;
        }

        /// <summary>
        /// 发送实时通知
        /// </summary>
        public async Task<ApiResult<bool>> SendRealtimeNotificationAsync(RealtimeNotificationDto notification)
        {
            var result = new ApiResult<bool>();
            try
            {
                // 保存到数据库
                var notificationEntity = new NotificationModel
                {
                    Title = notification.Title,
                    Content = notification.Content,
                    Type = notification.Type,
                    Tag = notification.Tag,
                    WorkOrderCode = notification.WorkOrderCode,
                    ProductionReportCode = notification.ProductionReportCode,
                    Priority = notification.Priority,
                    CreateTime = DateTime.Now,
                    CreateName = "系统"
                };

                await _notificationRepository.AddAsync(notificationEntity);
                notification.Id = notificationEntity.Id; // 更新实时通知ID

                // 发送实时通知
                await _hubContext.Clients.All.SendAsync("ReceiveNotification", notification);

                result.Code = ApiEnum.Success;
                result.Msg = "实时通知发送成功";
                result.Data = true;
            }
            catch (Exception ex)
            {
                result.Code = ApiEnum.Failed;
                result.Msg = $"实时通知发送失败: {ex.Message}";
                result.Data = false;
                _logger.LogError(ex, "发送实时通知失败");
            }
            return result;
        }

        /// <summary>
        /// 获取用户通知列表
        /// </summary>
        public async Task<ApiResult<ApiPaging<NotificationDto>>> GetUserNotificationsAsync(int userId, int pageIndex = 1, int pageSize = 10, bool? isRead = null)
        {
            var result = new ApiResult<ApiPaging<NotificationDto>>();
            try
            {
                var queryable = _notificationRepository.GetAll()
                    .Where(x => !x.Isdel && (x.UserId == null || x.UserId == userId));

                if (isRead.HasValue)
                {
                    queryable = queryable.Where(x => x.IsRead == isRead.Value);
                }

                var totalCount = queryable.Count();

                var items = queryable
                    .OrderByDescending(x => x.CreateTime)
                    .Skip((pageIndex - 1) * pageSize)
                    .Take(pageSize)
                    .ToList();

                var notificationDtos = items.Select(x => new NotificationDto
                {
                    Id = x.Id,
                    Title = x.Title,
                    Content = x.Content,
                    Type = x.Type,
                    TypeName = GetTypeName(x.Type),
                    WorkOrderCode = x.WorkOrderCode,
                    ProductionReportCode = x.ProductionReportCode,
                    Priority = x.Priority,
                    IsRead = x.IsRead,
                    CreateTime = x.CreateTime,
                    CreateName = x.CreateName
                }).ToList();

                var paging = new ApiPaging<NotificationDto>
                {
                    PageDatas = notificationDtos,
                    TotalCount = totalCount,
                    
                };

                result.Code = ApiEnum.Success;
                result.Msg = "查询成功";
                result.Data = paging;
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "获取用户通知列表失败");
                result.Code = ApiEnum.Failed;
                result.Msg = $"获取通知列表失败: {ex.Message}";
            }
            return result;
        }

        /// <summary>
        /// 获取未读通知数量
        /// </summary>
        public async Task<ApiResult<int>> GetUnreadNotificationCountAsync(int userId)
        {
            var result = new ApiResult<int>();
            try
            {
                var count = _notificationRepository.GetAll()
                    .Count(x => !x.Isdel && !x.IsRead && (x.UserId == null || x.UserId == userId));

                result.Code = ApiEnum.Success;
                result.Msg = "查询成功";
                result.Data = count;
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "获取未读通知数量失败");
                result.Code = ApiEnum.Failed;
                result.Msg = $"获取未读通知数量失败: {ex.Message}";
                result.Data = 0;
            }
            return result;
        }

        /// <summary>
        /// 标记通知为已读
        /// </summary>
        public async Task<ApiResult<bool>> MarkAsReadAsync(int notificationId, int userId)
        {
            var result = new ApiResult<bool> { Code = ApiEnum.Success, Data = true };
            try
            {
                var notification = await _notificationRepository.GetModelAsync(notificationId);
                if (notification == null || notification.Isdel || (notification.UserId.HasValue && notification.UserId.Value != userId))
                {
                    result.Code = ApiEnum.Failed;
                    result.Msg = "通知不存在或无权操作";
                    result.Data = false;
                    return result;
                }

                notification.IsRead = true;
                notification.UpdateTime = DateTime.Now;
                notification.UpdateName = "用户";

                var rows = await _notificationRepository.Update(notification);
                if (rows <= 0)
                {
                    result.Code = ApiEnum.Failed;
                    result.Msg = "标记已读失败";
                    result.Data = false;
                }
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, $"标记通知{notificationId}为已读失败");
                result.Code = ApiEnum.Failed;
                result.Msg = $"标记已读失败: {ex.Message}";
                result.Data = false;
            }
            return result;
        }

        /// <summary>
        /// 标记所有通知为已读
        /// </summary>
        public async Task<ApiResult<bool>> MarkAllAsReadAsync(int userId)
        {
            var result = new ApiResult<bool> { Code = ApiEnum.Success, Data = true };
            try
            {
                var unreadNotifications = _notificationRepository.GetAll()
                    .Where(x => !x.Isdel && !x.IsRead && (x.UserId == null || x.UserId == userId))
                    .ToList();

                foreach (var notification in unreadNotifications)
                {
                    notification.IsRead = true;
                    notification.UpdateTime = DateTime.Now;
                    notification.UpdateName = "用户";
                }

                var rows = await _notificationRepository.UpdateRange(unreadNotifications);
                if (rows <= 0)
                {
                    result.Code = ApiEnum.Failed;
                    result.Msg = "没有未读通知或标记失败";
                    result.Data = false;
                }
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, $"标记所有通知为已读失败，用户ID: {userId}");
                result.Code = ApiEnum.Failed;
                result.Msg = $"标记所有已读失败: {ex.Message}";
                result.Data = false;
            }
            return result;
        }

        /// <summary>
        /// 删除通知
        /// </summary>
        public async Task<ApiResult<bool>> DeleteNotificationAsync(int notificationId, int userId)
        {
            var result = new ApiResult<bool> { Code = ApiEnum.Success, Data = true };
            try
            {
                var notification = await _notificationRepository.GetModelAsync(notificationId);
                if (notification == null || notification.Isdel || (notification.UserId.HasValue && notification.UserId.Value != userId))
                {
                    result.Code = ApiEnum.Failed;
                    result.Msg = "通知不存在或无权操作";
                    result.Data = false;
                    return result;
                }

                notification.Isdel = true;
                notification.UpdateTime = DateTime.Now;
                notification.UpdateName = "用户";

                var rows = await _notificationRepository.Update(notification);
                if (rows <= 0)
                {
                    result.Code = ApiEnum.Failed;
                    result.Msg = "删除通知失败";
                    result.Data = false;
                }
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, $"删除通知{notificationId}失败");
                result.Code = ApiEnum.Failed;
                result.Msg = $"删除通知失败: {ex.Message}";
                result.Data = false;
            }
            return result;
        }

        #region 私有方法

        private string GetTypeName(int type)
        {
            return type switch
            {
                1 => "工单通知",
                2 => "报工单通知",
                3 => "系统通知",
                _ => "未知类型"
            };
        }

        #endregion
    }
}

